﻿// MyLogger.cpp
#define MYLOGGER_EXPORTS // 定义此宏以导出符号 (仅在此 DLL 项目中定义)

// 包含内部头文件，它定义了 MyLogger 类
#include "MyLogger.h"
// 包含公共 API 头文件，以确保声明与定义匹配
#include "MyLoggerAPI.h"

// --- 实现细节 ---
#define _CRT_SECURE_NO_WARNINGS // 禁用某些 CRT 安全警告
#define _SCL_SECURE_NO_WARNINGS // 禁用某些 STL 安全警告

// --- spdlog 包含 ---
#include <spdlog/spdlog.h>                  // spdlog 主要头文件
#include <spdlog/sinks/stdout_color_sinks.h> // 控制台 sink (带颜色)
#include <spdlog/sinks/rotating_file_sink.h> // 旋转文件 sink
#include <spdlog/common.h>                  // For spdlog::source_loc, spdlog::level::level_enum
#include <spdlog/fmt/ostr.h>                // 允许 spdlog 记录自定义类型 (如果需要的话)

// --- Qt 包含 (条件编译) ---
#ifdef QT_CORE_LIB
#include <spdlog/sinks/qt_sinks.h> // Qt sink
#include <QTextBrowser>
#include <QTextEdit>
#include <QObject> // qt_sink_mt 需要 QObject 支持元对象系统
// QMutex 和 QMutexLocker 在这里不再需要，因为 qt_sink_mt 内部处理
#endif

// --- Windows API 包含 ---
#include <windows.h> // Windows API 用于目录和文件操作
#include <pathcch.h> // 用于路径操作 (可选，如果不用 PathCch 功能)
#pragma comment(lib, "Pathcch.lib") // 链接 Pathcch.lib

// --- 标准库包含 ---
#include <vector>
#include <algorithm> // for std::sort
#include <chrono>    // for std::chrono::system_clock, std::chrono::seconds
#include <ctime>     // for std::time_t, std::tm, std::strftime, localtime_s
#include <iostream>  // for std::cerr (错误输出)
#include <mutex>     // for std::recursive_mutex, std::lock_guard
#include <memory>    // for std::shared_ptr, std::make_shared, std::unique_ptr
#include <string>    // for std::string
#include <exception> // for std::exception
#include <utility>   // for std::pair
#include <limits>    // 用于检查整数范围

// --- MyLoggerImpl 类定义 (Pimpl 实现) ---
// 这个类封装了所有日志记录的内部逻辑和状态
class MyLoggerImpl {
public:
	std::shared_ptr<spdlog::logger> file_logger; // 指向文件和控制台 logger 的共享指针
#ifdef QT_CORE_LIB
	std::shared_ptr<spdlog::logger> qt_logger;   // 指向 Qt logger 的共享指针
	std::shared_ptr<spdlog::sinks::qt_sink_mt> qt_sink; // 指向 Qt sink 的共享指针
	QTextBrowser* bound_browser = nullptr; // 指向绑定的 QTextBrowser 控件
	QTextEdit* bound_edit = nullptr;       // 指向绑定的 QTextEdit 控件
#endif
	std::recursive_mutex init_mutex; // 用于保护初始化过程的递归互斥锁
	int maxLogFiles;                 // 存储日志轮转时保留的最大文件数量

	// 构造函数 - 初始化成员变量
	MyLoggerImpl() : maxLogFiles(10) {} // 默认最大文件数为 10

	// 析构函数 - 确保 spdlog 资源被正确释放
	~MyLoggerImpl() {
		try {
			// 在程序退出前，刷新所有 logger 的缓冲区，确保日志写入
			if (file_logger) {
				file_logger->flush();
			}
#ifdef QT_CORE_LIB
			if (qt_logger) {
				qt_logger->flush();
			}
#endif
			// 关闭 spdlog，释放所有已注册的 logger 和全局资源
			spdlog::shutdown();
		}
		catch (const spdlog::spdlog_ex& ex) {
			// 在析构函数中捕获并报告 spdlog 异常，避免程序崩溃
			std::cerr << "MyLogger 错误 (spdlog): 关闭时发生异常: " << ex.what() << std::endl;
		}
		catch (const std::exception& ex) {
			// 捕获并报告其他标准异常
			std::cerr << "MyLogger 错误: 关闭时发生异常: " << ex.what() << std::endl;
		}
		catch (...) {
			// 捕获并报告未知异常
			std::cerr << "MyLogger 错误: 关闭时发生未知异常。" << std::endl;
		}
	}

	// 将自定义的 LogLevel 枚举转换为 spdlog 的 level::level_enum
	static spdlog::level::level_enum fromLogLevel(LogLevel level) {
		switch (level) {
		case LogLevel::Trace:    return spdlog::level::trace;
		case LogLevel::Debug:    return spdlog::level::debug;
		case LogLevel::Info:     return spdlog::level::info;
		case LogLevel::Warn:     return spdlog::level::warn;
		case LogLevel::Error:    return spdlog::level::err; // spdlog 使用 'err'
		case LogLevel::Critical: return spdlog::level::critical;
		case LogLevel::Off:      return spdlog::level::off;
		default:                 return spdlog::level::info; // 默认返回 Info 级别
		}
	}

	// 确保文件和控制台 logger 已初始化 (采用惰性初始化和线程安全锁)
	void ensureFileLoggerInitialized() {
		std::lock_guard<std::recursive_mutex> lock(init_mutex); // 获取初始化锁
		if (!file_logger) { // 检查是否已初始化 (Double-Checked Locking 模式简化版)
			try {
				// 1. 获取或创建日志目录
				std::string logDir = createLogDirectory(); // 使用 WinAPI 创建
				if (logDir.empty()) {
					std::cerr << "MyLogger 错误: 无法创建或访问日志目录。文件日志记录已禁用。" << std::endl;
					return; // 初始化失败，直接返回
				}

				// 2. 构造日志文件名 (基于当前日期)
				auto now = std::chrono::system_clock::now();
				std::time_t now_c = std::chrono::system_clock::to_time_t(now);
				std::tm now_tm;
				localtime_s(&now_tm, &now_c); // 使用 Windows 安全版本
				char dateStr[20];
				std::strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &now_tm);
				std::string baseFileName = "log_" + std::string(dateStr);
				std::string fileName = logDir + "\\" + baseFileName + ".txt";

				// 3. 创建 rotating_file_sink (旋转文件接收器, _mt 表示线程安全)
				//    使用成员变量 maxLogFiles 作为最大文件数
				auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
					fileName,                  // 文件路径
					1048576 * 10,              // 单个文件最大大小 (10MB)
					static_cast<size_t>(this->maxLogFiles), // 最大文件数
					false                      // rotate_on_open = false (启动时不旋转)
				);
				file_sink->set_level(spdlog::level::trace); // 文件记录所有级别的日志
				// 设置文件日志格式: [时间戳] [级别] [源文件:行号 函数名] 消息
				file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%# %!] %v");

				// 4. 创建 console_sink (控制台接收器, 带颜色, _mt 表示线程安全)
				auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
				console_sink->set_level(spdlog::level::trace); // 控制台也输出所有级别
				// 设置控制台日志格式 (可以与文件格式相同或不同)
				console_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%# %!] %v");

				// 5. 将 sinks 组合起来
				std::vector<spdlog::sink_ptr> sinks{ console_sink, file_sink };

				// 6. 创建 logger 实例
				file_logger = std::make_shared<spdlog::logger>("file_console_logger", sinks.begin(), sinks.end());
				file_logger->set_level(spdlog::level::trace); // 设置 logger 的全局最低记录级别

				// 7. 设置 flush 策略 (例如，警告及以上级别立即写入磁盘)
				file_logger->flush_on(spdlog::level::warn);

				// 8. 向 spdlog 注册此 logger
				spdlog::register_logger(file_logger);

				// 9. 设置全局定期 flush (可选)
				spdlog::flush_every(std::chrono::seconds(5));

			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 错误 (spdlog): 初始化文件 logger 失败: " << ex.what() << std::endl;
				file_logger.reset(); // 初始化失败，重置指针
			}
			catch (const std::exception& ex) {
				std::cerr << "MyLogger 错误: 初始化文件 logger 失败: " << ex.what() << std::endl;
				file_logger.reset();
			}
			catch (...) {
				std::cerr << "MyLogger 错误: 初始化文件 logger 时发生未知错误。" << std::endl;
				file_logger.reset();
			}
		} // 结束 if (!file_logger)
	} // 结束 ensureFileLoggerInitialized (锁自动释放)

#ifdef QT_CORE_LIB
	// 确保 Qt logger 已初始化 (线程安全)
	void ensureQtLoggerInitialized() {
		std::lock_guard<std::recursive_mutex> lock(init_mutex); // 获取初始化锁
		// 仅在 Qt logger 未初始化且已绑定了有效 Qt 控件时执行
		if (!qt_logger && (bound_browser || bound_edit)) {
			try {
				// 1. 创建 Qt Sink (_mt 表示线程安全)
				if (bound_browser) {
					qt_sink = std::make_shared<spdlog::sinks::qt_sink_mt>(bound_browser, "append");
				}
				else { // bound_edit 必须为 true
					qt_sink = std::make_shared<spdlog::sinks::qt_sink_mt>(bound_edit, "appendPlainText");
				}

				// 2. 设置 Qt sink 的级别和格式
				qt_sink->set_level(spdlog::level::trace);
				qt_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v"); // 简洁格式

				// 3. 创建 logger
				std::vector<spdlog::sink_ptr> sinks{ qt_sink };
				qt_logger = std::make_shared<spdlog::logger>("qt_logger", sinks.begin(), sinks.end());
				qt_logger->set_level(spdlog::level::trace);

				// 4. 注册 logger
				spdlog::register_logger(qt_logger);

			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 错误 (spdlog): 初始化 Qt logger 失败: " << ex.what() << std::endl;
				qt_logger.reset(); // 初始化失败，重置指针
				qt_sink.reset();
			}
			catch (const std::exception& ex) {
				std::cerr << "MyLogger 错误: 初始化 Qt logger 失败: " << ex.what() << std::endl;
				qt_logger.reset();
				qt_sink.reset();
			}
			catch (...) {
				std::cerr << "MyLogger 错误: 初始化 Qt logger 时发生未知错误。" << std::endl;
				qt_logger.reset();
				qt_sink.reset();
			}
		} // 结束 if (!qt_logger && ...)
	} // 结束 ensureQtLoggerInitialized (锁自动释放)

	// 绑定 QTextBrowser (内部实现, 线程安全)
	void bindQtWidgetInternal(QTextBrowser* textBrowser) {
		std::lock_guard<std::recursive_mutex> lock(init_mutex); // 获取初始化锁
		if (bound_browser == textBrowser && textBrowser != nullptr) return; // 已经是同一个，无需操作

		// 如果之前存在 Qt logger，先注销并清理资源
		if (qt_logger) {
			try {
				spdlog::drop("qt_logger"); // 从 spdlog 全局注册表中移除
			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 警告 (spdlog): 注销旧的 qt_logger 失败: " << ex.what() << std::endl;
			}
			qt_logger.reset(); // 释放 logger 对象的共享指针
			qt_sink.reset();   // 释放 sink 对象的共享指针
		}

		// 更新绑定状态
		bound_browser = textBrowser;
		bound_edit = nullptr; // 清除另一个可能的绑定

		// 如果绑定了新的非空控件，则尝试初始化 Qt logger
		if (bound_browser) {
			ensureQtLoggerInitialized();
		}
	} // 结束 bindQtWidgetInternal (锁自动释放)

	// 绑定 QTextEdit (内部实现, 线程安全)
	void bindQtWidgetInternal(QTextEdit* textEdit) {
		std::lock_guard<std::recursive_mutex> lock(init_mutex); // 获取初始化锁
		if (bound_edit == textEdit && textEdit != nullptr) return; // 已经是同一个

		// 如果之前存在 Qt logger，先注销并清理资源
		if (qt_logger) {
			try {
				spdlog::drop("qt_logger");
			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 警告 (spdlog): 注销旧的 qt_logger 失败: " << ex.what() << std::endl;
			}
			qt_logger.reset();
			qt_sink.reset();
		}

		// 更新绑定状态
		bound_edit = textEdit;
		bound_browser = nullptr;

		// 如果绑定了新的非空控件，则尝试初始化 Qt logger
		if (bound_edit) {
			ensureQtLoggerInitialized();
		}
	} // 结束 bindQtWidgetInternal (锁自动释放)
#endif // QT_CORE_LIB

	// 创建日志目录 (使用 Windows API, 兼容 C++14)
	std::string createLogDirectory() {
		char buffer[MAX_PATH];
		// 获取当前进程可执行文件的完整路径 (ANSI 版本)
		if (GetModuleFileNameA(nullptr, buffer, MAX_PATH) == 0) {
			DWORD error = GetLastError();
			std::cerr << "MyLogger 错误: GetModuleFileNameA 获取可执行文件路径失败。错误码: " << error << std::endl;
			return ""; // 返回空字符串表示失败
		}

		std::string exePath = std::string(buffer);
		// 查找路径中最后一个路径分隔符 (\ 或 /)
		size_t lastSlash = exePath.find_last_of("\\/");
		if (lastSlash == std::string::npos) {
			std::cerr << "MyLogger 错误: 无法从路径确定可执行文件目录: " << exePath << std::endl;
			return ""; // 无法解析路径
		}
		// 构建日志目录的路径 (在可执行文件同级目录下创建 "logs" 子目录)
		std::string logDir = exePath.substr(0, lastSlash) + "\\logs";

		// 在尝试创建目录之前，先管理（清理）该目录下的旧日志文件
		// manageLogFiles 函数会处理目录尚不存在的情况
		if (!manageLogFiles(logDir)) {
			// manageLogFiles 内部会打印警告信息
			std::cerr << "MyLogger 警告: 管理日志文件时遇到问题，目录: '" << logDir << "'" << std::endl;
			// 即使管理失败，仍然继续尝试创建目录
		}

		// 尝试创建日志目录 (ANSI 版本)
		if (CreateDirectoryA(logDir.c_str(), nullptr)) {
			// 目录成功创建
			return logDir;
		}
		else {
			DWORD error = GetLastError();
			// 如果错误码表示目录已存在，则视为成功
			if (error == ERROR_ALREADY_EXISTS) {
				return logDir;
			}
			else {
				// 其他创建目录时发生的错误
				std::cerr << "MyLogger 错误: 创建日志目录 '" << logDir << "' 失败。CreateDirectoryA 失败。错误码: " << error << std::endl;
				return ""; // 返回空字符串表示失败
			}
		}
	} // 结束 createLogDirectory

	// 管理日志文件 (删除旧文件，保留最新的 maxLogFiles 个) (使用 Windows API)
	bool manageLogFiles(const std::string& logDir) {
		// 将 UTF-8 编码的 std::string (logDir) 转换为 Windows API 使用的宽字符 (UTF-16)
		// 1. 获取需要的缓冲区大小
		int size_needed = MultiByteToWideChar(CP_UTF8, 0, logDir.c_str(), static_cast<int>(logDir.size()), nullptr, 0);
		if (size_needed <= 0) {
			// 如果目录不存在，转换可能失败 (GetLastError 可能返回 ERROR_PATH_NOT_FOUND 等)
			// 这不一定是错误，因为后面会尝试创建目录，所以返回 true 允许继续
			return true;
		}
		// 2. 分配缓冲区并进行转换
		std::wstring wLogDir;
		wLogDir.resize(size_needed);
		if (MultiByteToWideChar(CP_UTF8, 0, logDir.c_str(), static_cast<int>(logDir.size()), &wLogDir[0], size_needed) == 0) {
			std::cerr << "MyLogger 错误: MultiByteToWideChar 将日志目录路径转换为宽字符串失败。错误码: " << GetLastError() << std::endl;
			return false; // 转换失败，无法继续
		}

		// 构建文件搜索模式，例如 "C:\path\to\logs\log_*.txt"
		std::wstring searchPattern = wLogDir + L"\\log_*.txt";
		WIN32_FIND_DATAW findFileData; // 用于存储找到的文件信息 (宽字符版本)
		HANDLE hFind = FindFirstFileW(searchPattern.c_str(), &findFileData); // 开始查找文件

		// 用于存储找到的日志文件名和它们的最后写入时间
		std::vector<std::pair<std::wstring, FILETIME>> files;

		// 检查 FindFirstFileW 的结果
		if (hFind == INVALID_HANDLE_VALUE) {
			DWORD error = GetLastError();
			// 如果错误是“文件未找到”或“路径未找到”，说明没有旧日志或目录不存在，这是正常情况
			if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
				return true; // 没有文件需要管理，操作成功
			}
			// 其他查找错误，记录警告但允许程序继续
			std::wcerr << L"MyLogger 警告: 访问日志目录进行清理时出错: '" << wLogDir << L"'。FindFirstFileW 失败。错误码: " << error << std::endl;
			// 即使出错，也返回 true，避免阻止日志功能
			return true;
		}

		bool errorDuringOperation = false; // 标记在枚举或删除过程中是否发生了错误
		// 循环查找所有匹配的文件
		do {
			// 忽略子目录，只处理文件
			if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
				std::wstring fileName = findFileData.cFileName;
				// 简单检查文件名格式，确保是 log_YYYY-MM-DD.txt 形式
				// 长度至少为 15 (log_YYYY-MM-DD.txt)
				if (fileName.rfind(L"log_", 0) == 0 && fileName.length() >= 15 && fileName.substr(fileName.length() - 4) == L".txt") {
					// 存储文件名和最后修改时间
					files.emplace_back(fileName, findFileData.ftLastWriteTime);
				}
			}
		} while (FindNextFileW(hFind, &findFileData) != 0); // 继续查找下一个匹配的文件

		// 检查 FindNextFileW 循环结束后的最终错误状态
		DWORD dwError = GetLastError();
		FindClose(hFind); // 关闭文件查找句柄，释放资源

		// 如果最后一个错误不是 ERROR_NO_MORE_FILES，说明查找过程中出现了问题
		if (dwError != ERROR_NO_MORE_FILES) {
			std::wcerr << L"MyLogger 警告: 枚举日志文件时出错: '" << wLogDir << L"'。FindNextFileW 失败。错误码: " << dwError << std::endl;
			errorDuringOperation = true; // 标记发生了错误
		}

		// 使用成员变量 maxLogFiles 进行比较
		// 确保 maxLogFiles 至少为 1，并转换为 size_t 进行比较
		size_t maxFilesAllowed = (this->maxLogFiles > 0) ? static_cast<size_t>(this->maxLogFiles) : 1;
		// 如果找到的日志文件数量超过了允许的最大值
		if (files.size() > maxFilesAllowed) {
			// 按文件的最后写入时间升序排序 (最旧的文件排在前面)
			std::sort(files.begin(), files.end(), [](const auto& a, const auto& b) {
				// CompareFileTime 返回值: <0 (a<b), 0 (a=b), >0 (a>b)
				return CompareFileTime(&a.second, &b.second) < 0;
				});

			// 使用 maxFilesAllowed 计算需要删除的文件数量
			int filesToDelete = static_cast<int>(files.size()) - maxFilesAllowed;
			// 删除最旧的文件
			for (int i = 0; i < filesToDelete; ++i) {
				std::wstring fullPath = wLogDir + L"\\" + files[i].first; // 构建要删除文件的完整路径
				if (!DeleteFileW(fullPath.c_str())) { // 尝试删除文件 (宽字符版本)
					DWORD deleteError = GetLastError();
					// 如果错误不是“文件未找到”(可能已被其他进程删除)，则记录警告
					if (deleteError != ERROR_FILE_NOT_FOUND) {
						std::wcerr << L"MyLogger 警告: 删除旧日志文件失败: '" << fullPath << L"'。错误码: " << deleteError << std::endl;
						errorDuringOperation = true; // 标记发生了错误
					}
				}
			}
		}

		// 如果整个过程中没有报告错误，则返回 true
		return !errorDuringOperation;
	} // 结束 manageLogFiles


	// --- 核心日志记录方法 (接收格式化好的字符串) ---

	// 记录到文件/控制台 logger
	void log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
		ensureFileLoggerInitialized(); // 确保文件/控制台 logger 已初始化
		if (file_logger) {
			try {
				// 创建 spdlog 的源文件位置信息结构体
				spdlog::source_loc loc{ file, line, function };
				// 调用 logger 的 log 方法进行记录
				// 使用 spdlog::string_view_t 可以避免不必要的字符串拷贝
				file_logger->log(loc, fromLogLevel(level), spdlog::string_view_t(message.data(), message.size()));
			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 错误 (spdlog): 记录到文件/控制台时出错: " << ex.what() << std::endl;
			}
			catch (const std::exception& ex) {
				std::cerr << "MyLogger 错误: 记录到文件/控制台时出错: " << ex.what() << std::endl;
			}
			catch (...) {
				std::cerr << "MyLogger 错误: 记录到文件/控制台时发生未知异常。" << std::endl;
			}
		}
	} // 结束 log

#ifdef QT_CORE_LIB
	// 记录到 Qt logger
	void qt_log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
		ensureQtLoggerInitialized(); // 确保 Qt logger 已初始化 (如果控件已绑定)
		if (qt_logger) {
			// qt_sink_mt 内部处理了线程安全，这里无需外部加锁
			try {
				spdlog::source_loc loc{ file, line, function }; // Qt sink 通常不显示源位置，但 API 需要
				qt_logger->log(loc, fromLogLevel(level), spdlog::string_view_t(message.data(), message.size()));
			}
			catch (const spdlog::spdlog_ex& ex) {
				std::cerr << "MyLogger 错误 (spdlog): 记录到 Qt 时出错: " << ex.what() << std::endl;
			}
			catch (const std::exception& ex) {
				std::cerr << "MyLogger 错误: 记录到 Qt 时出错: " << ex.what() << std::endl;
			}
			catch (...) {
				std::cerr << "MyLogger 错误: 记录到 Qt 时发生未知异常。" << std::endl;
			}
		}
	} // 结束 qt_log

	// 同时记录到文件/控制台和 Qt logger
	void both_log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
		// 先记录到文件/控制台 (内部会检查初始化)
		log(level, file, line, function, message);
		// 再记录到 Qt (内部会检查初始化)
		qt_log(level, file, line, function, message);
	} // 结束 both_log
#endif // QT_CORE_LIB
}; // --- End of MyLoggerImpl Class ---


// --- MyLogger Class Implementation (公共接口的内部实现) ---

// 获取单例实例 (线程安全的 Meyers' Singleton)
MyLogger& MyLogger::getInstance() {
	static MyLogger instance; // C++11 保证静态局部变量的初始化是线程安全的
	return instance;
}

// 构造函数 - 初始化 Pimpl 指针和日志开关状态
MyLogger::MyLogger() : pimpl(std::make_unique<MyLoggerImpl>()), loggingEnabled(false) { // 默认禁用日志
	// 不在构造函数中进行 logger 初始化，采用惰性初始化策略
}

// 析构函数 - 使用默认实现，std::unique_ptr 会自动管理 pimpl 的销毁
MyLogger::~MyLogger() = default;

// 设置日志启用/禁用状态
void MyLogger::setLoggingEnabled(bool enabled) {
	loggingEnabled = enabled;
}

// 检查日志是否启用
bool MyLogger::isLoggingEnabled() const {
	return loggingEnabled;
}

// 实现设置最大文件数的内部公共方法
void MyLogger::setMaxFilesInternal(int count) {
	// 检查 pimpl 是否有效 (理论上 getInstance 后总应有效)
	if (!pimpl) {
		std::cerr << "MyLogger 错误: Pimpl 无效，无法设置最大文件数。" << std::endl;
		return;
	}
	// 在访问 pimpl 成员前加锁，确保线程安全（尽管通常在单线程环境设置）
	std::lock_guard<std::recursive_mutex> lock(pimpl->init_mutex);
	pimpl->maxLogFiles = count;
	// 注意：此更改只影响未来创建的 rotating_file_sink，不会影响已经创建的 sink。
}

#ifdef QT_CORE_LIB
// 绑定 QTextBrowser 控件
void MyLogger::bindQtWidget(QTextBrowser* textBrowser) {
	if (pimpl) {
		pimpl->bindQtWidgetInternal(textBrowser);
	}
}

// 绑定 QTextEdit 控件
void MyLogger::bindQtWidget(QTextEdit* textEdit) {
	if (pimpl) {
		pimpl->bindQtWidgetInternal(textEdit);
	}
}
#endif // QT_CORE_LIB

// --- MyLogger 类内部日志方法实现 (调用 pimpl) ---

// 通用日志方法 (供特定级别方法调用)
void MyLogger::log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
	// 仅在日志启用且 pimpl 有效时记录
	if (!loggingEnabled || !pimpl) return;
	pimpl->log(level, file, line, function, message);
}

// 特定级别的日志方法
void MyLogger::info(const char* file, int line, const char* function, const std::string& message) {
	log(LogLevel::Info, file, line, function, message);
}
void MyLogger::warn(const char* file, int line, const char* function, const std::string& message) {
	log(LogLevel::Warn, file, line, function, message);
}
void MyLogger::error(const char* file, int line, const char* function, const std::string& message) {
	log(LogLevel::Error, file, line, function, message);
}
void MyLogger::critical(const char* file, int line, const char* function, const std::string& message) {
	log(LogLevel::Critical, file, line, function, message);
}

#ifdef QT_CORE_LIB
// 通用 Qt 日志方法
void MyLogger::qt_log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
	if (!loggingEnabled || !pimpl) return;
	pimpl->qt_log(level, file, line, function, message);
}
// 特定级别的 Qt 日志方法
void MyLogger::qt_info(const char* file, int line, const char* function, const std::string& message) {
	qt_log(LogLevel::Info, file, line, function, message);
}
void MyLogger::qt_warn(const char* file, int line, const char* function, const std::string& message) {
	qt_log(LogLevel::Warn, file, line, function, message);
}
void MyLogger::qt_error(const char* file, int line, const char* function, const std::string& message) {
	qt_log(LogLevel::Error, file, line, function, message);
}
void MyLogger::qt_critical(const char* file, int line, const char* function, const std::string& message) {
	qt_log(LogLevel::Critical, file, line, function, message);
}
// 通用 Both 日志方法
void MyLogger::both_log(LogLevel level, const char* file, int line, const char* function, const std::string& message) {
	if (!loggingEnabled || !pimpl) return;
	pimpl->both_log(level, file, line, function, message);
}
// 特定级别的 Both 日志方法
void MyLogger::both_info(const char* file, int line, const char* function, const std::string& message) {
	both_log(LogLevel::Info, file, line, function, message);
}
void MyLogger::both_warn(const char* file, int line, const char* function, const std::string& message) {
	both_log(LogLevel::Warn, file, line, function, message);
}
void MyLogger::both_error(const char* file, int line, const char* function, const std::string& message) {
	both_log(LogLevel::Error, file, line, function, message);
}
void MyLogger::both_critical(const char* file, int line, const char* function, const std::string& message) {
	both_log(LogLevel::Critical, file, line, function, message);
}
#endif // QT_CORE_LIB


// --- 公共 API 函数定义 ---
// 这些函数是 DLL 导出的 C 风格接口，供 MyLoggerAPI.h 中的声明使用

MYLOGGER_API void MyLogger_SetEnabled(bool enabled) {
	MyLogger::getInstance().setLoggingEnabled(enabled);
}

MYLOGGER_API bool MyLogger_IsEnabled() {
	return MyLogger::getInstance().isLoggingEnabled();
}

// 实现设置最大文件数的公共接口
MYLOGGER_API void MyLogger_SetMaxFiles(int count) {
	// 进行基本的合理性检查，确保 count 大于 0
	if (count <= 0) {
		std::cerr << "MyLogger 警告: SetMaxFiles 调用了无效的参数 (" << count << ")。至少需要保留 1 个文件。将使用 1。" << std::endl;
		count = 1;
	}
	// 设置一个实际的上限，防止意外设置过大的值导致问题
	if (count > 1000) { // 例如，限制最多保留 1000 个文件
		std::cerr << "MyLogger 警告: SetMaxFiles 设置的值 (" << count << ") 过大。将限制为 1000。" << std::endl;
		count = 1000;
	}

	// 调用 MyLogger 的公共成员函数来设置值
	MyLogger::getInstance().setMaxFilesInternal(count);
}


#ifdef QT_CORE_LIB
MYLOGGER_API void MyLogger_BindBrowser(QTextBrowser* textBrowser) {
	MyLogger::getInstance().bindQtWidget(textBrowser);
}

MYLOGGER_API void MyLogger_BindEdit(QTextEdit* textEdit) {
	MyLogger::getInstance().bindQtWidget(textEdit);
}
#endif // QT_CORE_LIB


// --- 内部日志函数定义 ---
// 这些函数由 MyLoggerAPI.h 中的宏调用，它们仅仅是 MyLogger 对应方法的简单包装

MYLOGGER_API void Internal_LogInfo(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().info(file, line, function, message);
}
MYLOGGER_API void Internal_LogWarn(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().warn(file, line, function, message);
}
MYLOGGER_API void Internal_LogError(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().error(file, line, function, message);
}
MYLOGGER_API void Internal_LogCritical(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().critical(file, line, function, message);
}

#ifdef QT_CORE_LIB
MYLOGGER_API void Internal_QtInfo(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().qt_info(file, line, function, message);
}
MYLOGGER_API void Internal_QtWarn(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().qt_warn(file, line, function, message);
}
MYLOGGER_API void Internal_QtError(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().qt_error(file, line, function, message);
}
MYLOGGER_API void Internal_QtCritical(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().qt_critical(file, line, function, message);
}
MYLOGGER_API void Internal_BothInfo(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().both_info(file, line, function, message);
}
MYLOGGER_API void Internal_BothWarn(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().both_warn(file, line, function, message);
}
MYLOGGER_API void Internal_BothError(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().both_error(file, line, function, message);
}
MYLOGGER_API void Internal_BothCritical(const char* file, int line, const char* function, const std::string& message) {
	MyLogger::getInstance().both_critical(file, line, function, message);
}
#endif // QT_CORE_LIB